//
// Created by machiry on 12/28/16.
//

#ifndef PROJECT_VULNERABILITYWARNING_H
#define PROJECT_VULNERABILITYWARNING_H

#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/DebugLoc.h"
#include "llvm/Pass.h"
#include "llvm/PassAnalysisSupport.h"
#include "llvm/Analysis/AliasSetTracker.h"
#include "llvm/IR/InstVisitor.h"
#include "llvm/IR/CFG.h"


using namespace llvm;
namespace DRCHECKER {
    /***
     * This represents a common class for all vulnerability warnings.
     */
    class VulnerabilityWarning {
    public:
        std::vector<Instruction*> trace;
        std::vector<Instruction*> callSiteTrace;
        std::string warning_string;
        Instruction* target_instr;
        std::string found_by;

        VulnerabilityWarning(std::vector<Instruction*> *callTrace,
                             std::vector<Instruction*> *srcTrace, std::string warningMsg,
                             Instruction *targetInstr, std::string found_by) {
            this->target_instr = targetInstr;
            this->warning_string = warningMsg;
            this->trace.insert(this->trace.end(), srcTrace->begin(), srcTrace->end());
            this->callSiteTrace.insert(this->callSiteTrace.end(), callTrace->begin(), callTrace->end());
            this->found_by = found_by;
        }

        /***
         * Print complete warning message to the provided raw stream.
         * @param O raw stream to which the output should be written to.
         */
        virtual void printCompleteWarning(llvm::raw_ostream& O) const;

        /***
         *  Print a normal warning message to the provided output stream.
         * @param O raw stream to which the output should be written to.
         */
        virtual void printWarning(llvm::raw_ostream& O) const;

        /***
         *  get the trace of the call sites to this function where the warning was
         *  generated.
         * @return pointer to the list of instruction representing call sites.
         */
        virtual std::vector<Instruction*>* getCallSiteTrace() {
            return &(this->callSiteTrace);
        }



        virtual bool isSameVulWarning(VulnerabilityWarning *toCheck) {
            if(toCheck != nullptr) {
                return this->target_instr == toCheck->target_instr &&
                       this->warning_string.compare(toCheck->warning_string) == 0 &&
                       this->found_by.compare(toCheck->found_by) == 0;
            }
            return false;
        }
    };
}

#endif //PROJECT_VULNERABILITYWARNING_H
